use std::sync::Arc;
use async_trait::async_trait;
use chrono::{DateTime, Local};
use log::info;
use tokio::sync::mpsc::{unbounded_channel};
use crate::connection_manager::event::ConnectionEvent;
use crate::{create_default_rpc_codecs, DefaultLocalSeqCreator, RpcChannel, RpcContext, RpcEvent, RpcResult};
use crate::sender::RpcSender;
use crate::session::RpcSession;

pub struct RpcTestChannel;

#[async_trait]
impl RpcChannel for RpcTestChannel {
    async fn write(&mut self, _local_seq: String, data: Vec<u8>, _timeout: u32) -> RpcResult<Vec<u8>> {
        info!("send data: {}", String::from_utf8(data).unwrap());
        Ok(Vec::new())
    }
}

impl RpcSender {

    pub fn test_sender() -> RpcSender {
        let (sender, _receiver) = unbounded_channel::<Box<dyn ConnectionEvent>>();
        let (event_sender, _event_receiver) = unbounded_channel::<Box<dyn RpcEvent>>();
        RpcSender::new(sender, event_sender)
    }
}

impl RpcContext {

    pub fn test_context() -> RpcContext {
        RpcContext::new(RpcSender::test_sender())
    }

    pub fn test_context_with_codec_type(codec_type: &'static str) -> RpcContext {
        let context = RpcContext::new(RpcSender::test_sender());
        context.session().set_current_codec_type(Some(codec_type.to_string()));
        context
    }
}

impl RpcSession {

    pub fn test_session() -> RpcSession {
        let now: DateTime<Local> = Local::now();
        let prefix = format!("{}", now.format("%Y%m%d%H%M%S"));
        RpcSession::new(Arc::new(Box::new(DefaultLocalSeqCreator::new(prefix))), create_default_rpc_codecs())
    }
}
